package com.iot.ruler.core;


import com.iot.ruler.caster.RulerPublisherIns;
import com.iot.ruler.caster.RulerSubject;
import com.iot.ruler.caster.RulerSubscriber;
import jakarta.annotation.Resource;


/**
 * 通用规则抽象
 * 范型说明：T - 规则标识数据类型，E - 监听的Event类型, D - 规则判定结果数据类型
 *
 * @author lzb
 * @Date 2022/8/26 22:21
 */
public abstract class Ruler<E extends RulerSubject<?>, T, D> extends RulerSubscriber<E> {

    /**
     * 内部发布者，用于将主题发布出去
     */
    protected final RulerPublisherIns publisher = RulerPublisherIns.getInstance();
    /**
     * 独立运行时，定制化线程池
     */
    @Resource
    private RulerRuntime runtime;

    /**
     * 获取规则标识，此处可再封装，利用Enum进行包装以方便Rules统一管理
     *
     * @return 规则标识
     */
    public abstract T getTag();

    /**
     * 单一规则判定条件
     *
     * @param subject 接收到的事件
     * @return true/false - 是否满足条件
     */
    public abstract boolean condition(E subject);

    /**
     * 规则执行，在监听到数据变化后自动被调用
     *
     * @param subject 事件
     */
    public abstract void apply(E subject);

    /**
     * 发射数据，可直接在此处做最终处理亦可发送给下一个规则
     *
     * @param result 可以是一组字符串如：sql语句，也可以是一个对象：DTO对象
     */
    public abstract void publish(D result);

    /**
     * 主题消息回调
     *
     * @param subject 主题，携带数据
     */
    @Override
    protected void onSubject(E subject) {
        runtime.offer(() -> apply(subject));
    }

}
